package Master.interfaces;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Set;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;

import Master.Configurations;
import Master.MasterEngine;
import Master.Resource;
import Master.Task;
import Master.TaskPlan;
import Module.StatusService.JobStatus;
import Module.StatusService.WorkerStatus;
import java.util.Hashtable;

public class MonitorScreen extends ClientGUI{
	/*
	 * GUI Components
	 */
	private JLabel job_text = new JLabel("Job Status");
	private JLabel worker_text = new JLabel("Worker Status");
	private JProgressBar progress_bar = new JProgressBar();
	private JLabel throbber = new JLabel(new ImageIcon("client_images/gui/throbber.gif"));
	private JButton exit_btn = new JButton("Close this monitor");
	
	private JLabel budget_text=new JLabel("Budget");
	private JLabel deadline_text=new JLabel("Deadline");
	private JLabel elapsed_time_text=new JLabel("Elapsed time");
	private JLabel job_done_text=new JLabel("Jobs completed");
	private JLabel cost_text=new JLabel("Total actual cost");
	private JLabel strategy_text=new JLabel("Strategy");
	
	private JLabel budget_text_data=new JLabel();
	private JLabel deadline_text_data=new JLabel();
	private JLabel elapsed_time_text_data=new JLabel();
	private JLabel job_done_text_data=new JLabel();
	private JLabel cost_text_data=new JLabel();
	private JLabel strategy_text_data=new JLabel();
	
	private DisplayScrollPanel job_scroller = new DisplayScrollPanel();
	private DisplayScrollPanel worker_scroller = new DisplayScrollPanel();
	
	/*
	 * Variables
	 */
	private int max_cols=5;
	private InputScreen inputscreen_gui=null;
	
	private Hashtable <Integer, JobPanelItem > jobs;
	private Hashtable <Integer, WorkerPanelItem > workers;

	public MonitorScreen() {
		super();

		progress_bar.setPreferredSize(new Dimension(Configurations.screenWidth-60, 20));
		progress_bar.setFont(new Font(null, Font.BOLD, 14));
		progress_bar.setStringPainted(true);
		progress_bar.setForeground(Color.DARK_GRAY);
		progress_bar.setBackground(Color.WHITE);
		
		jobs=new Hashtable<Integer, JobPanelItem>();
		workers=new Hashtable<Integer, WorkerPanelItem>();
		
		this.setVisible(true);
	}

	public void display(Container screen_container) {		
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.HORIZONTAL;
		screen_container.setLayout(new FlowLayout());
		
		/*
		 * Jobs
		 */
		JPanel job_p = new JPanel();
		job_p.setLayout(new GridBagLayout());
		screen_container.add(job_p);
		
		c.gridx = 0;
		c.gridy = 0;
		job_p.add(job_text,c);
		
		c.gridx = 0;
		c.gridy = 1;
		job_p.add(job_scroller,c);
		job_scroller.setPreferredSize(new Dimension(Configurations.screenWidth-50,340));
		
		/*
		 * Workers
		 */
		JPanel worker_p = new JPanel();
		worker_p.setLayout(new GridBagLayout());
		screen_container.add(worker_p);
		
		c.gridx = 0;
		c.gridy = 0;
		worker_p.add(worker_text,c);
		
		c.gridx = 0;
		c.gridy = 1;
		worker_p.add(worker_scroller,c);
		worker_scroller.setPreferredSize(new Dimension(Configurations.screenWidth-50,180));
		
		/*
		 * Info
		 */
		JPanel misc_p = new JPanel();
		misc_p.setLayout(new GridBagLayout());
		screen_container.add(misc_p);
		
		JPanel info_p = new JPanel();
		info_p.setBorder(BorderFactory.createTitledBorder("Execution Info"));
		info_p.setLayout(new GridBagLayout());
		c.gridx = 0;
		c.gridy = 0;
		c.insets=new Insets(0, 5, 0, 5);
		misc_p.add(info_p,c);
		
		c.gridx = 0;
		c.gridy = 0;
		c.insets=new Insets(2, 5, 2, 5);
		info_p.add(budget_text,c);
		
		c.gridx = 0;
		c.gridy = 1;
		info_p.add(deadline_text,c);
		
		c.gridx = 0;
		c.gridy = 2;
		info_p.add(strategy_text,c);
		
		c.gridx = 2;
		c.gridy = 0;
		info_p.add(elapsed_time_text,c);
		
		c.gridx = 2;
		c.gridy = 1;
		info_p.add(cost_text,c);
		
		c.gridx = 2;
		c.gridy = 2;
		info_p.add(job_done_text,c);
		
		c.gridx = 1;
		c.gridy = 0;
		info_p.add(budget_text_data,c);
		
		c.gridx = 1;
		c.gridy = 1;
		info_p.add(deadline_text_data,c);
		
		c.gridx = 1;
		c.gridy = 2;
		info_p.add(strategy_text_data,c);
		
		c.gridx = 3;
		c.gridy = 0;
		info_p.add(elapsed_time_text_data,c);
		
		c.gridx = 3;
		c.gridy = 1;
		info_p.add(cost_text_data,c);
		
		c.gridx = 3;
		c.gridy = 2;
		info_p.add(job_done_text_data,c);
		
		c.insets=new Insets(0, 0, 0, 0);
		
		JPanel job_legend_p = new JPanel();
		job_legend_p.setBorder(BorderFactory.createTitledBorder("Job Legends"));
		job_legend_p.setLayout(new GridBagLayout());
		c.gridx = 1;
		c.gridy = 0;
		c.insets=new Insets(0, 5, 0, 5);
		misc_p.add(job_legend_p,c);
		setUpJobLegends(job_legend_p);
		
		JPanel worker_legend_p = new JPanel();
		worker_legend_p.setBorder(BorderFactory.createTitledBorder("Worker Legends"));
		worker_legend_p.setLayout(new GridBagLayout());
		c.gridx = 2;
		c.gridy = 0;
		c.insets=new Insets(0, 5, 0, 5);
		misc_p.add(worker_legend_p,c);
		setUpWorkerLegends(worker_legend_p);
		
		/*
		 * Buttons
		 */
		JPanel button_p = new JPanel();
		button_p.setBorder(BorderFactory.createTitledBorder("Actions"));
		button_p.setLayout(new GridBagLayout());
		
		c.insets=new Insets(0, 5, 0, 5);
		misc_p.add(button_p);
		
		c.gridx = 0;
		c.gridy = 0;
		c.insets=new Insets(0, 5, 5, 5);
		button_p.add(exit_btn,c);
		c.insets=new Insets(0, 0, 0, 0);
		
		/*
		 * Progress bar
		 */
		JPanel progress_p = new JPanel();
		progress_p.setLayout(new FlowLayout());
		screen_container.add(progress_p);
		
		progress_p.add(throbber);
		progress_p.add(progress_bar);
	}

	protected void initialise_listeners() {
		exit_btn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				close();
			}
		});
	}
	
	private void close()
	{
		this.dispose();
	}
	
    public void updateProgressBar(int completed)
	{
		progress_bar.setValue(completed);
		progress_bar.setString("Completed - "+completed+"%");
		
		Set keys = jobs.keySet();
		int count_done=0;
		for(Object k:keys)
		{
			JobPanelItem this_item = jobs.get(k);
			if(this_item.isDone())
				count_done++;
		}
		
		this.job_done_text_data.setText(count_done+" / "+jobs.size());
	}
    
    public void setStartInfo(TaskPlan taskPlan){
    	this.budget_text_data.setText(""+taskPlan.getBudget());
    	this.deadline_text_data.setText(""+taskPlan.getTimeRequired());
    	this.strategy_text_data.setText(MasterEngine.algorithmFlag.toString());
    	this.elapsed_time_text_data.setText("-");
    	this.cost_text_data.setText("-");
    }
    
    public void setFinishedInfo(float time, float cost){
    	this.elapsed_time_text_data.setText(String.format("%.3f", time));
    	this.cost_text_data.setText(String.format("%.2f", cost));
    }
	
	public void setInputScreen(InputScreen inputscreen_gui)
	{
		this.inputscreen_gui=inputscreen_gui;
	}
	
	public void initWorkerStatus()
	{
		int col_count=0;
		int row_count=0;
		int size=this.inputscreen_gui.getResources().size();
		System.out.println(size);
        int i = 1;
        for(Resource resource : this.inputscreen_gui.getResources()) {
        	WorkerPanelItem new_worker = new WorkerPanelItem(resource.getID(),resource);
            this.workers.put(i, new_worker);
            i++;
            if(col_count>=max_cols)
			{
				col_count=0;
				row_count++;
			}
			worker_scroller.add(col_count++,row_count,new_worker);
        }
	}
	
	public void initJobStatus(TaskPlan taskplan)
	{
		int col_count=0;
		int row_count=0;
        int size = taskplan.getTasks().size();
        int i = 1;
        for(Task task : taskplan.getTasks()){
        	JobPanelItem new_job = new JobPanelItem(task.getTaskID(),task);
            this.jobs.put(i, new_job);
            i++;

            if(col_count>=max_cols)
			{
				col_count=0;
				row_count++;
			}
			
			job_scroller.add(col_count++,row_count,new_job);
        }
	}
	
	public void updateJobStatus(int Resourceid, int jobId, JobStatus jobstatus)
	{
		JobPanelItem jpi=this.jobs.get(jobId);
		jpi.setStatus(jobstatus);
	}
	
	public void updateWorkerStatus(Hashtable<Integer, WorkerStatus>  workerstatus)
	{
		for(int i=1;i<workerstatus.size()+1;i++)
		{
			this.workers.get(i).setStatus(workerstatus.get(i));
		}
	}
	
	private void setUpJobLegends(Container container)
	{
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.HORIZONTAL;
		c.insets=new Insets(2, 5, 2, 5);
		
		JLabel prepared_text=new JLabel("Prepared");
		JLabel ready_text=new JLabel("Wait");
		JLabel running_text=new JLabel("Running");
		JLabel done_text=new JLabel("Done");
		JLabel failed_text=new JLabel("Failed");
		JLabel cancel_text=new JLabel("Cancelled");
		
		JPanel prepared_color = new JPanel();
		JPanel ready_color = new JPanel();
		JPanel running_color = new JPanel();
		JPanel done_color = new JPanel();
		JPanel failed_color = new JPanel();
		JPanel cancel_color = new JPanel();
		
		/*
		 * Colors
		 */
		c.gridx = 0;
		c.gridy = 0;
		container.add(prepared_color,c);
		prepared_color.setPreferredSize(new Dimension(15,15));
		prepared_color.setBackground(new Color(Integer.parseInt(Configurations.J_PREPARED_COLOR,16)));
		
		c.gridx = 0;
		c.gridy = 1;
		container.add(ready_color,c);
		ready_color.setPreferredSize(new Dimension(15,15));
		ready_color.setBackground(new Color(Integer.parseInt(Configurations.J_READY_COLOR,16)));
		
		c.gridx = 0;
		c.gridy = 2;
		container.add(running_color,c);
		running_color.setPreferredSize(new Dimension(15,15));
		running_color.setBackground(new Color(Integer.parseInt(Configurations.J_RUNNING_COLOR,16)));
		
		c.gridx = 2;
		c.gridy = 0;
		container.add(done_color,c);
		done_color.setPreferredSize(new Dimension(15,15));
		done_color.setBackground(new Color(Integer.parseInt(Configurations.J_DONE_COLOR,16)));
		
		c.gridx = 2;
		c.gridy = 1;
		container.add(failed_color,c);
		failed_color.setPreferredSize(new Dimension(15,15));
		failed_color.setBackground(new Color(Integer.parseInt(Configurations.J_FAILED_COLOR,16)));
		
		c.gridx = 2;
		c.gridy = 2;
		container.add(cancel_color,c);
		cancel_color.setPreferredSize(new Dimension(15,15));
		cancel_color.setBackground(new Color(Integer.parseInt(Configurations.J_CANCEL_COLOR,16)));
		
		/*
		 * Text
		 */
		c.gridx = 1;
		c.gridy = 0;
		container.add(prepared_text,c);
		prepared_text.setForeground(new Color(Integer.parseInt(Configurations.J_PREPARED_COLOR,16)));
		
		c.gridx = 1;
		c.gridy = 1;
		container.add(ready_text,c);
		ready_text.setForeground(new Color(Integer.parseInt(Configurations.J_READY_COLOR,16)));
		
		c.gridx = 1;
		c.gridy = 2;
		container.add(running_text,c);
		running_text.setForeground(new Color(Integer.parseInt(Configurations.J_RUNNING_COLOR,16)));
		
		c.gridx = 3;
		c.gridy = 0;
		container.add(done_text,c);
		done_text.setForeground(new Color(Integer.parseInt(Configurations.J_DONE_COLOR,16)));
		
		c.gridx = 3;
		c.gridy = 1;
		container.add(failed_text,c);
		failed_text.setForeground(new Color(Integer.parseInt(Configurations.J_FAILED_COLOR,16)));
		
		c.gridx = 3;
		c.gridy = 2;
		container.add(cancel_text,c);
		cancel_text.setForeground(new Color(Integer.parseInt(Configurations.J_CANCEL_COLOR,16)));
	}
	
	private void setUpWorkerLegends(Container container)
	{
		GridBagConstraints c = new GridBagConstraints();
		c.fill = GridBagConstraints.HORIZONTAL;
		c.insets=new Insets(2, 5, 2, 5);
		
		JLabel idle_text=new JLabel("Idle");
		JLabel dead_text=new JLabel("Not responding");
		JLabel running_text=new JLabel("Running");
		
		JPanel idle_color = new JPanel();
		JPanel dead_color = new JPanel();
		JPanel running_color = new JPanel();
		
		/*
		 * Colors
		 */
		c.gridx = 0;
		c.gridy = 0;
		container.add(idle_color,c);
		idle_color.setPreferredSize(new Dimension(15,15));
		idle_color.setBackground(new Color(Integer.parseInt(Configurations.W_IDLE_COLOR,16)));
		
		c.gridx = 0;
		c.gridy = 1;
		container.add(dead_color,c);
		dead_color.setPreferredSize(new Dimension(15,15));
		dead_color.setBackground(new Color(Integer.parseInt(Configurations.W_DEAD_COLOR,16)));
		
		c.gridx = 0;
		c.gridy = 2;
		container.add(running_color,c);
		running_color.setPreferredSize(new Dimension(15,15));
		running_color.setBackground(new Color(Integer.parseInt(Configurations.W_RUNNING_COLOR,16)));
		
		/*
		 * Text
		 */
		c.gridx = 1;
		c.gridy = 0;
		container.add(idle_text,c);
		idle_text.setForeground(new Color(Integer.parseInt(Configurations.W_IDLE_COLOR,16)));
		
		c.gridx = 1;
		c.gridy = 1;
		container.add(dead_text,c);
		dead_text.setForeground(new Color(Integer.parseInt(Configurations.W_DEAD_COLOR,16)));
		
		c.gridx = 1;
		c.gridy = 2;
		container.add(running_text,c);
		running_text.setForeground(new Color(Integer.parseInt(Configurations.W_RUNNING_COLOR,16)));
	}

}
